// Package biz @author <chengjiang@buffalo-robot.com>
// @date 2023/3/3
// @note
package biz

import (
	"context"
	"fmt"
	"github.com/go-kratos/kratos/v2/log"
	"gorm.io/gorm"
	pb "phm/api/phm/v1"
	"phm/api/phm/v1/bigscreen"
	"phm/models/generator/model"
	"phm/tools"
	"phm/tools/javaApi"
	"time"
)

type RaRadarRepo interface {
	CreateRaRadar(ctx context.Context, uModel *model.RaRadar, db *gorm.DB) error
	UpdateRaRadar(ctx context.Context, uModel *model.RaRadar, db *gorm.DB) error
	DeleteRaRadarByIds(ctx context.Context, ids []string, db *gorm.DB) error
	GetRaRadarById(ctx context.Context, id string) (*model.RaRadar, error)
	GetRaRadarByIds(ctx context.Context, ids []string) ([]*model.RaRadar, error)
	GetRaRadarList(ctx context.Context, query string, pageNum, pageSize int64) ([]*model.RaRadar, error)
	// GetDB 得到db以方便事务处理
	GetDB() *gorm.DB
	// CreateRaStation /* ra station */
	CreateRaStation(ctx context.Context, uModel *model.RaStation, db *gorm.DB) error
	UpdateRaStation(ctx context.Context, uModel *model.RaStation, db *gorm.DB) error
	DeleteRaStationByIds(ctx context.Context, ids []string, db *gorm.DB) error
	GetRaStationById(ctx context.Context, id string) (*model.RaStation, error)
	GetRaStationByIds(ctx context.Context, ids []string) ([]*model.RaStation, error)
	GetRaStationList(ctx context.Context, query string, pageNum, pageSize int64) ([]*model.RaStation, error)

	// CreateRaServerArea for area bind
	CreateRaServerArea(ctx context.Context, uModel *model.RaServerArea, db *gorm.DB) error
	UpdateRaServerArea(ctx context.Context, uModel *model.RaServerArea, db *gorm.DB) error
	DeleteRaServerAreaByIds(ctx context.Context, ids []string, db *gorm.DB) error
	GetRaServerAreaById(ctx context.Context, id string) (*model.RaServerArea, error)
	GetRaServerAreaByIds(ctx context.Context, ids []string) ([]*model.RaServerArea, error)
	GetRaServerAreaList(ctx context.Context, query string, pageNum, pageSize int64) ([]*model.RaServerArea, error)

	// CreateFiRadarType the radar type here
	CreateFiRadarType(ctx context.Context, uModel *model.FiRadarType, db *gorm.DB) error
	UpdateFiRadarType(ctx context.Context, uModel *model.FiRadarType, db *gorm.DB) error
	DeleteFiRadarTypeByIds(ctx context.Context, ids []string, db *gorm.DB) error
	GetFiRadarTypeById(ctx context.Context, id string) (*model.FiRadarType, error)
	GetFiRadarTypeByIds(ctx context.Context, ids []string) ([]*model.FiRadarType, error)
	GetFiRadarTypeList(ctx context.Context, query string, pageNum, pageSize int64) ([]*model.FiRadarType, error)

	// GetRadarSubSystem 大屏部分：
	// 获取雷达分系统：
	GetRadarSubSystem(ctx context.Context, id string) ([]*bigscreen.SubSystemReply_SubSystemItem, error)
}

type RaRadarUseCase struct {
	radar            RaRadarRepo
	timeTaskRes      TimedTaskFaultResultRepo
	sysParameterRepo SysParameterRepo
	log              *log.Helper
}

func NewRaRadarUseCase(radar RaRadarRepo, timeTaskRes TimedTaskFaultResultRepo, sysParameterRepo SysParameterRepo, logger log.Logger) *RaRadarUseCase {
	return &RaRadarUseCase{
		radar:            radar,
		timeTaskRes:      timeTaskRes,
		sysParameterRepo: sysParameterRepo,
		log:              log.NewHelper(logger),
	}
}

// SimulateRadarDataCron 定时：/pc/ta/v1/simulationData
func (r *RaRadarUseCase) SimulateRadarDataCron() {
	url := "/pc/ta/v1/simulationData"
	start, end := 1, 0
	// 每天凌晨4点执行
	startDate := time.Now()
	endDate := startDate.Add(24 * time.Hour)
	radarId, radarTypeId := "47ad1a046ff949708c7909989e975d34", "72a4063f888f48408edf2bbf592808da"
	// 开始仿真
	code, err := javaApi.PostJavaRpcServ(url, javaApi.PostBody{
		EndDataTime:        endDate.Format("2006-01-02 15:04:05"),
		RadarId:            radarId,
		RadarTypeId:        radarTypeId,
		SimulationDataType: 2,
		StartDataTime:      startDate.Format("2006-01-02 15:04:05"),
		State:              int32(start),
	})
	if err != nil {
		r.log.Error("SimulateRadarDataCron", "err", err)
	}
	if code != "200" {
		r.log.Error("SimulateRadarDataCron is not 200: ", "code", code)
		return
	}
	// 睡眠1小时
	time.Sleep(1 * time.Hour)
	// 获取id
	body4Simulate, err := javaApi.GetJavaRpcServ4Simulate(url)
	if err != nil {
		r.log.Error("SimulateRadarDataCron Get:", "err", err)
	}
	if body4Simulate == nil || len(body4Simulate.Data) <= 0 || body4Simulate.Data == nil || body4Simulate.Code != "200" {
		r.log.Error("SimulateRadarDataCron Get is not 200: ", "code", body4Simulate.Code)
		return
	}
	id := body4Simulate.Data[0]["id"].(string)
	// 结束仿真
	code, err = javaApi.PostJavaRpcServ(url, javaApi.PostBody{
		Id:                 &id,
		EndDataTime:        endDate.Format("2006-01-02 15:04:05"),
		RadarId:            radarId,
		RadarTypeId:        radarTypeId,
		SimulationDataType: 2,
		StartDataTime:      startDate.Format("2006-01-02 15:04:05"),
		State:              int32(end),
	})
	if err != nil {
		r.log.Error("SimulateRadarDataCron", "err", err)
	}
	if code != "200" {
		r.log.Error("SimulateRadarDataCron is not 200: ", "code", code)
		return
	}
	r.log.Info("SimulateRadarDataCron", "success")
}

func (r *RaRadarUseCase) GetRaStationMap() (*pb.GetRaStationMapRep, error) {
	radars, err := r.radar.GetRaRadarList(context.Background(), "", 0, 0)
	if err != nil {
		return nil, err
	}
	raStations, err := r.radar.GetRaStationList(context.Background(), "", 0, 0)
	if err != nil {
		return nil, err
	}
	raServerAreas, err := r.radar.GetRaServerAreaList(context.Background(), "", 0, 0)
	if err != nil {
		return nil, err
	}
	fiRadarTypes, err := r.radar.GetFiRadarTypeList(context.Background(), "", 0, 0)
	if err != nil {
		return nil, err
	}
	// map
	var radarMap = make(map[string]*model.RaRadar)
	var stationMap = make(map[string]*model.RaStation)
	var serverAreaMap = make(map[string]*model.RaServerArea)
	var typeMap = make(map[string]*model.FiRadarType)
	for _, radar := range radars {
		radarMap[radar.ID] = radar
	}
	for _, station := range raStations {
		stationMap[*station.ID] = station
	}
	for _, area := range raServerAreas {
		serverAreaMap[*area.ID] = area
	}
	for _, radarType := range fiRadarTypes {
		typeMap[radarType.ID] = radarType
	}
	var res = make([]*pb.StationMap, 0, len(radars))
	for _, radar := range radars {
		if v, ok := stationMap[*radar.SiteID]; ok {
			if area, ok := serverAreaMap[*v.AreaID]; ok {
				if _, ok := typeMap[*radar.TypeID]; ok {
					var isTable int32 = 1
					if radar.DataTableName == nil {
						isTable = 0
					}
					var installationPosition = ""
					if radar.InstallationPosition != nil {
						installationPosition = *radar.InstallationPosition
					}
					res = append(res, &pb.StationMap{
						AreaName:             *area.Name,
						StationName:          *v.Name,
						Name:                 *radar.Name,
						InstallationPosition: installationPosition,
						InstallTime:          tools.Time2String(radar.InstallTime),
						Latitude:             fmt.Sprintf("%v", *v.Latitude),
						Longitude:            fmt.Sprintf("%v", *v.Longitude),
						Id:                   radar.ID,
						AreaId:               *area.ID,
						IsTable:              isTable,
					})
				}
			}
		}
	}
	return &pb.GetRaStationMapRep{RaRadarMapVOS: res}, nil
}

func (r *RaRadarUseCase) GetRaStationMapStatus() (*pb.GetRaStationMapStatusRep, error) {
	radars, err := r.radar.GetRaRadarList(context.Background(), "", 0, 0)
	if err != nil {
		return nil, err
	}
	raStations, err := r.radar.GetRaStationList(context.Background(), "", 0, 0)
	if err != nil {
		return nil, err
	}
	raServerAreas, err := r.radar.GetRaServerAreaList(context.Background(), "", 0, 0)
	if err != nil {
		return nil, err
	}
	fiRadarTypes, err := r.radar.GetFiRadarTypeList(context.Background(), "", 0, 0)
	if err != nil {
		return nil, err
	}
	// map
	var radarMap = make(map[string]*model.RaRadar)
	var stationMap = make(map[string]*model.RaStation)
	var serverAreaMap = make(map[string]*model.RaServerArea)
	var typeMap = make(map[string]*model.FiRadarType)
	for _, radar := range radars {
		radarMap[radar.ID] = radar
	}
	for _, station := range raStations {
		stationMap[*station.ID] = station
	}
	for _, area := range raServerAreas {
		serverAreaMap[*area.ID] = area
	}
	for _, radarType := range fiRadarTypes {
		typeMap[radarType.ID] = radarType
	}
	// 查看雷达状态
	var radarIdList = make([]string, 0, len(radars))
	for _, radar := range radars {
		radarIdList = append(radarIdList, radar.ID)
	}
	timeTaskforRadar, err := r.timeTaskRes.GetTimedTaskFaultResultByRadarIdList(context.Background(), radarIdList)
	if err != nil {
		return nil, err
	}
	var res = make([]*pb.GetRaStationMapStatusRep_MapStatus, 0, len(radars))
	for _, radar := range radars {
		if v, ok := stationMap[*radar.SiteID]; ok {
			if area, ok := serverAreaMap[*v.AreaID]; ok {
				if radarType, ok := typeMap[*radar.TypeID]; true {
					radarTypeName, tabShap := "", ""
					var status = -1
					if timeTaskforRadar[radar.ID] != nil &&
						timeTaskforRadar[radar.ID].NonSwitchFault != nil &&
						timeTaskforRadar[radar.ID].NonSwitchLow != nil &&
						timeTaskforRadar[radar.ID].SwitchFault != nil {
						if *timeTaskforRadar[radar.ID].NonSwitchFault != 0 && *timeTaskforRadar[radar.ID].SwitchFault != 0 {
							status = 2
						} else if *timeTaskforRadar[radar.ID].NonSwitchLow != 0 {
							status = 1
						} else {
							status = 0
						}
					} else {
						status = 3
					}
					if !ok {
						status = 4
					} else {
						radarTypeName = *radarType.Name
						tabShap = *radarType.TabShap
					}
					var isTable int32 = 1
					if radar.DataTableName == nil {
						isTable = 0
					}
					var installationPosition = ""
					if radar.InstallationPosition != nil {
						installationPosition = *radar.InstallationPosition
					}
					res = append(res, &pb.GetRaStationMapStatusRep_MapStatus{
						AreaId:               *area.ID,
						AreaName:             *area.Name,
						Id:                   radar.ID,
						InstallTime:          tools.Time2String(radar.InstallTime),
						InstallationPosition: installationPosition,
						IsTableData:          isTable,
						Latitude:             fmt.Sprintf("%v", *v.Latitude),
						Longitude:            fmt.Sprintf("%v", *v.Longitude),
						Name:                 *radar.Name,
						RadarTypeName:        radarTypeName,
						StationName:          *v.Name,
						Status:               int32(status),
						TabShap:              tabShap,
						//TableName:            *radar.DataTableName,
					})
				}
			}
		}
	}
	return &pb.GetRaStationMapStatusRep{RaRadarMapVOS: res}, nil
}

// GetRadarById get radar by id
func (r *RaRadarUseCase) GetRadarById(ctx context.Context, id string) (*pb.GetRaRadarsListRep, error) {
	radar, err := r.radar.GetRaRadarById(ctx, id)
	if err != nil {
		return nil, err
	}
	// 拿到站点
	station, err := r.radar.GetRaStationById(ctx, *radar.SiteID)
	if err != nil {
		return nil, err
	}
	radarType, err := r.radar.GetFiRadarTypeById(ctx, *radar.TypeID)
	if err != nil {
		return nil, err
	}
	// 拿area
	area, err := r.radar.GetRaServerAreaById(ctx, *station.AreaID)
	isTable := 0
	if radar.DataTableName != nil {
		isTable = 1
	}
	return &pb.GetRaRadarsListRep{
		AreaId:        *area.ID,
		AreaName:      *area.Name,
		Id:            radar.ID,
		IsTableData:   int32(isTable),
		Name:          *radar.Name,
		RadarTypeName: *radarType.Name,
		StationName:   *station.Name,
		Status:        int32(*radar.Status),
	}, nil
}

func (r *RaRadarUseCase) GetRadarSubSystem(ctx context.Context, id string) ([]*bigscreen.SubSystemReply_SubSystemItem, error) {
	return r.radar.GetRadarSubSystem(ctx, id)
}
